package palf.commands {
import org.flexunit.asserts.assertTrue;
import org.flexunit.rules.IMethodRule;
import org.mockito.integrations.flexunit4.MockitoRule;
import org.mockito.integrations.inOrder;
import org.mockito.integrations.mock;
import org.mockito.integrations.never;
import org.mockito.integrations.verify;

[Mock(type="palf.commands.Command")]
public class MacroCommandTest {

	[Rule]
	public var mockito : IMethodRule = new MockitoRule();

	public function MacroCommandTest() {

	}

	[Test]
	public function IsCommand() : void {
		var macro : MacroCommand = new MacroCommand();
		assertTrue(macro is Command);
	}

	[Test]
	public function macroRunsAddedCommands() : void {
		var command : Command = mock(Command);
		verify(never()).that(command.execute());

		var macro : MacroCommand = new MacroCommand();
		macro.addCommand(command);
		macro.execute();
		verify().that(command.execute());
	}

	[Test]
	public function onExecuteMacroCommandCallsAllStoredCommands() : void {
		var command01 : Command = mock(Command);
		var command02 : Command = mock(Command);
		var command03 : Command = mock(Command);

		var macro : MacroCommand = new MacroCommand();
		macro.addCommand(command01);
		macro.addCommand(command02);
		macro.addCommand(command03);
		verify(never()).that(command01.execute());
		verify(never()).that(command02.execute());
		verify(never()).that(command03.execute());

		macro.execute();
		inOrder().verify().that(command01.execute());
		inOrder().verify().that(command02.execute());
		inOrder().verify().that(command03.execute());
	}

	[Test]
	public function macroRunsEmbeddedMacro() : void {
		var outerMacro : MacroCommand = new MacroCommand();
		var innerMacro : MacroCommand = new MacroCommand();
		var command : Command = mock(Command);

		outerMacro.addCommand(innerMacro);
		innerMacro.addCommand(command);
		verify(never()).that(command.execute());

		outerMacro.execute();
		verify().that(innerMacro.execute());
		verify().that(command.execute());
	}

	[Test(expects="palf.commands.CommandError")]
	public function macrosCannotContainThemselves() : void {
		var macro : MacroCommand = new MacroCommand();
		macro.addCommand(macro);
		macro.execute();
	}

	[Test(expects="palf.commands.CommandError")]
	public function macrosCannotFormSimpleLoop() : void {
		var outerMacro : MacroCommand = new MacroCommand();
		var innerMacro : MacroCommand = new MacroCommand();

		outerMacro.addCommand(innerMacro);
		innerMacro.addCommand(outerMacro);
		outerMacro.execute();
	}

	[Test(expects="palf.commands.CommandError")]
	public function macrosCannotFormComplexLoop() : void {
		var outerMacro : MacroCommand = new MacroCommand();
		var middleMacro : MacroCommand = new MacroCommand();
		var innerMacro : MacroCommand = new MacroCommand();

		outerMacro.addCommand(middleMacro);
		middleMacro.addCommand(innerMacro);
		innerMacro.addCommand(outerMacro);
	}
}
}
